/*
 * @Descripttion: 自定义合成事件(处理冒泡)
 * @Author: lukasavage
 * @Date: 2021-12-27 22:01:02
 * @LastEditors: lukasavage
 * @LastEditTime: 2022-09-16 23:06:02
 */

import { updateQueue } from './component2';

/**
 * 自定义合成事件核心函数
 * @param {HTMLElement} dom 要绑定的事件DOM元素，例如button
 * @param {*} eventType 代表事件类型，例如onclick
 * @param {*} handler 事件处理函数
 */
function addEvent(dom, eventType, handler) {
    // 注意：下面的store是一个自定义属性，主要是用来手机事件类型和处理函数的
	let store = dom._store || (dom._store = {});
	store[eventType] = handler;
	if (!document[eventType]) document[eventType] = dispatchEvent;
}
function dispatchEvent(nativeEvent) {
	updateQueue.isBatchingUpdate = true;
	let { type, target } = nativeEvent;
	let eventType = `on${type}`; // onclick
	let syntheticEvent = createSyntheticEvent(nativeEvent);

	/* ①、此处以冒泡的形式依次触发 */
	while (target) {
		let { _store } = target;
		let handler = _store && _store[eventType];
		if (handler) handler(syntheticEvent);
		if (syntheticEvent.isPropagationStopped) break;
        // 将target循环向上移，从而实现冒泡
		target = target.parentNode;
	}

	updateQueue.batchUpdate();
}

function createSyntheticEvent(nativeEvent) {
	let syntheticEvent = {};
    // 把原生事件上的属性拷贝到合成事件对象上去
	for (const key in nativeEvent) {
		let value = nativeEvent[key];
		if (typeof value === 'function') value = value.bind(nativeEvent);
		syntheticEvent[key] = value;
	}
	syntheticEvent.nativeEvent = nativeEvent;

	syntheticEvent.isPropagationStopped = false; // 重置冒泡状态
	syntheticEvent.stopPropagation = stopPropagation; 
	syntheticEvent.defaultPrevented = false; // 重置默认行为装填
	syntheticEvent.preventDefault = preventDefault;

	return syntheticEvent;
}
function stopPropagation() {
    const event = this.nativeEvent;
    console.log(event.stopPropagation);
	if (event.stopPropagation) {
		// 标准浏览器
		event.stopPropagation();
	} else {
		// IE
		event.cancelBubble = true;
	}
	this.isPropagationStopped = true;
}
function preventDefault() {
	const event = this.nativeEvent;
	if (event.stopPropagation) {
		// 标准浏览器
		event.preventDefault();
	} else {
		// IE
		event.cancelBubble = true;
	}
	this.defaultPrevented = true;
}

export { addEvent };
